package com.yaxin.outsourcing.service.impl;

import cn.hutool.extra.qrcode.QrCodeUtil;

import java.io.*;

import cn.hutool.extra.qrcode.QrConfig;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.extension.toolkit.Db;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import com.yaxin.common.core.domain.PageQuery;
import com.yaxin.common.core.domain.entity.SysUser;
import com.yaxin.common.core.page.TableDataInfo;
import com.yaxin.outsourcing.domain.vo.OutsourcingPersonVO;
import com.yaxin.outsourcing.domain.dto.OutsourcingPersonDTO;
import com.yaxin.outsourcing.domain.po.AccessApplication;
import com.yaxin.outsourcing.domain.po.OutsourcingPerson;
import com.yaxin.outsourcing.enums.PersonStatus;
import com.yaxin.outsourcing.mapper.AccessApplicationMapper;
import com.yaxin.outsourcing.mapper.OutsourcingPersonMapper;
import com.yaxin.outsourcing.service.IOutsourcingPersonService;
import com.yaxin.outsourcing.utils.CardPrinterUtil;
import com.yaxin.outsourcing.utils.CardSheetUtil;
import com.yaxin.system.mapper.SysUserMapper;
import com.yaxin.system.service.ISysOssService;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import javax.imageio.ImageIO;
import javax.print.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.print.PrinterJob;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.net.URL;

/**
 * <p>
 * 外协人员信息表 服务实现类
 * </p>
 *
 * @author zcc
 * @since 2025-07-29
 */


@Service
public class OutsourcingPersonServiceImpl extends ServiceImpl<OutsourcingPersonMapper, OutsourcingPerson> implements IOutsourcingPersonService {

    @Autowired
    private OutsourcingPersonMapper outsourcingPersonMapper;

    @Autowired
    private AccessApplicationMapper accessApplicationMapper;

    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    private ISysOssService sysOssService;

    private static final String ALGORITHM = "AES";
    private static final String TRANSFORMATION = "AES/ECB/PKCS5Padding";

    @Override
    public Long addOutsourcingPerson(OutsourcingPersonDTO dto) {
        // 1. 根据申请单号查询申请单
        if(dto.getAppId() == null){

        }
        AccessApplication application = accessApplicationMapper.selectOne(
            new LambdaQueryWrapper<AccessApplication>()
                .eq(AccessApplication::getId, dto.getAppId())
        );
        if (application == null) {
            throw new RuntimeException("申请单不存在");
        }

        // 2. 校验当前人员数量是否超过申请人数（使用封装方法）
        checkPersonCountLimit(dto.getAppId());

        // 3. 校验身份证号是否已存在
        long idCardCount = outsourcingPersonMapper.selectCount(
            new LambdaQueryWrapper<OutsourcingPerson>()
                .eq(OutsourcingPerson::getIdCard, dto.getIdCard())
        );
        if (idCardCount > 0) {
            throw new RuntimeException("身份证号已存在");
        }

        // 4. 创建人员记录
        OutsourcingPerson person = new OutsourcingPerson();
        BeanUtils.copyProperties(dto, person);
        person.setAppId(application.getId());
        person.setStatus(PersonStatus.NORMAL); // 状态：1-正常
        person.setCreateTime(LocalDateTime.now());
        person.setUpdateTime(LocalDateTime.now());
        person.setCreatedBy(dto.getCreatedBy());
        person.setUpdatedBy(dto.getCreatedBy());
        person.setIsDeleted(0); // 设置逻辑删除字段默认值：未删除

        // 设置IC卡编号
        setIcNoForPerson(person);

        // 5. 保存到数据库
        outsourcingPersonMapper.insert(person);

        return person.getPerId();
    }

    @Override
    public boolean updateOutPerson(Long id, OutsourcingPerson person) {
        // 1. 检查要更新的外协人员是否存在
        OutsourcingPerson existingPerson = outsourcingPersonMapper.selectById(id);
        if (existingPerson == null) {
            throw new RuntimeException("外协人员不存在");
        }

        // 2. 如果修改了appId，检查人数限制
        if (person.getAppId() != null && !person.getAppId().equals(existingPerson.getAppId())) {
            checkPersonCountLimit(person.getAppId());
        }

        // 3. 根据申请单ID查询申请单（直接使用person的appId）
        AccessApplication application = accessApplicationMapper.selectById(person.getAppId());
        if (application == null) {
            throw new RuntimeException("申请单不存在");
        }

        // 4. 校验身份证号是否已被其他人员使用
        long idCardCount = outsourcingPersonMapper.selectCount(
            new LambdaQueryWrapper<OutsourcingPerson>()
                .eq(OutsourcingPerson::getIdCard, person.getIdCard())
                .ne(OutsourcingPerson::getPerId, id) // 排除自己
        );
        if (idCardCount > 0) {
            throw new RuntimeException("身份证号已存在");
        }

        // 5. 直接使用传入的person对象，只需设置必要字段
        person.setPerId(id); // 设置主键
        person.setAppId(application.getId());
        person.setUpdateTime(LocalDateTime.now());

        // 6. 执行更新操作
        return this.updateById(person);
    }

    @Override
    public OutsourcingPerson getPersonDetailById(Long id) {
        OutsourcingPerson person = outsourcingPersonMapper.selectById(id);
        String appNo = accessApplicationMapper.selectOne(
                new LambdaQueryWrapper<AccessApplication>()
                        .eq(AccessApplication::getId, person.getAppId())
        ).getAppNo();
        person.setAppNo(appNo);
        try{
            person.setCreatedByUser(sysUserMapper.selectOne(
                new LambdaQueryWrapper<SysUser>()
                    .eq(SysUser::getUserName, person.getCreatedBy())
            ).getNickName());
            person.setUpdatedByUser(sysUserMapper.selectOne(
                new LambdaQueryWrapper<SysUser>()
                    .eq(SysUser::getUserName, person.getUpdatedBy())
            ).getNickName());
        } catch (Exception e) {
            person.setCreatedByUser("unknown");
            person.setUpdatedByUser("unknown");
        }
        // 修改原代码为以下内容：
        if (StringUtils.isNotBlank(person.getIdCardBack())) {
            Long idCardBackId = Long.parseLong(person.getIdCardBack());
            person.setIdCardBackUrl(sysOssService.getById(idCardBackId).getUrl());
        }
        if (StringUtils.isNotBlank(person.getIdCardFront())) {
            Long idCardFrontId = Long.parseLong(person.getIdCardFront());
            person.setIdCardFrontUrl(sysOssService.getById(idCardFrontId).getUrl());
        }
        if (StringUtils.isNotBlank(person.getPortraitPhoto())) {
            Long portraitPhotoId = Long.parseLong(person.getPortraitPhoto());
            person.setPortraitPhotoUrl(sysOssService.getById(portraitPhotoId).getUrl());
        }
            return person;
    }

    @Override
    public Boolean deletePerson(List<Long> ids) {
        // 1. 参数校验
        if (CollectionUtils.isEmpty(ids)) {
            throw new IllegalArgumentException("人员ID列表不能为空");
        }

        // 2. 批量逻辑删除外协人员
        boolean isPersonDeleted = outsourcingPersonMapper.update(null,
            new LambdaUpdateWrapper<OutsourcingPerson>()
                .in(OutsourcingPerson::getPerId, ids)  // 注意这里是人员自己的ID
                .set(OutsourcingPerson::getIsDeleted, 2)
                .set(OutsourcingPerson::getUpdateTime, LocalDateTime.now())
        ) > 0;
        // 4. 返回操作结果
        if (!isPersonDeleted) {
            throw new RuntimeException("删除人员失败，可能ID不存在或已被删除");
        }
        return isPersonDeleted;
    }

    @Override
    public Void statusCheck() {
        // 获取当前时间
        LocalDateTime now = LocalDateTime.now();

        // 查询所有未删除且状态为正常的人员
        List<OutsourcingPerson> persons = outsourcingPersonMapper.selectList(
            new LambdaQueryWrapper<OutsourcingPerson>()
                .eq(OutsourcingPerson::getIsDeleted, 0)
                .eq(OutsourcingPerson::getStatus, PersonStatus.NORMAL)
        );
        List<OutsourcingPerson> persons_2 = outsourcingPersonMapper.selectList(
            new LambdaQueryWrapper<OutsourcingPerson>()
                .eq(OutsourcingPerson::getIsDeleted, 0)
                .eq(OutsourcingPerson::getStatus, PersonStatus.FAILURE)
        );

        // 过滤出 endTime 小于当前时间的人员（已过期）
        List<OutsourcingPerson> expiredPersons = persons.stream()
            .filter(person ->
                (person.getEndTime() != null && person.getEndTime().isBefore(now)) ||  // endTime 已过期
                    (person.getEntryTime() != null && person.getEntryTime().isAfter(now))  // entryTime 未到
            )
            .collect(Collectors.toList());
        List<OutsourcingPerson> vaildPersons = persons_2.stream()
            .filter(person ->
                person.getEntryTime() != null && person.getEntryTime().isBefore(now) &&  // entryTime 已到
                    person.getEndTime() != null && person.getEndTime().isAfter(now)          // endTime 未过期
            )
            .collect(Collectors.toList());

        // 批量更新状态为过期
        if (!expiredPersons.isEmpty()) {
            List<OutsourcingPerson> personsToUpdate = expiredPersons.stream()
                .map(person -> new OutsourcingPerson()
                    .setPerId(person.getPerId())
                    .setStatus(PersonStatus.FAILURE) // 设置为过期状态
                    .setUpdateTime(now))
                .collect(Collectors.toList());

            // 批量更新
            updateBatchById(personsToUpdate);


            // 记录日志
//            log.info("检测到 {} 名外协人员已过期，状态已更新", expiredPersons.size());
        }
        if(!vaildPersons.isEmpty()) {
            List<OutsourcingPerson> persons2ToUpdate = vaildPersons.stream()
                .map(person -> new OutsourcingPerson()
                    .setPerId(person.getPerId())
                    .setStatus(PersonStatus.NORMAL) // 设置为过期状态
                    .setUpdateTime(now))
                .collect(Collectors.toList());

            updateBatchById(persons2ToUpdate);
        }
        return null;
    }

    @Override
    public void checkPersonCountLimit(Long appId) {
        if (appId == null) {
            return; // 如果appId为空则不检查
        }

        // 1. 查询申请单
        AccessApplication application = accessApplicationMapper.selectById(appId);
        if (application == null) {
            throw new RuntimeException("申请单不存在");
        }

        // 2. 查询当前人员数量
        long currentPersonCount = outsourcingPersonMapper.selectCount(
            new LambdaQueryWrapper<OutsourcingPerson>()
                .eq(OutsourcingPerson::getAppId, appId)
                .eq(OutsourcingPerson::getIsDeleted, 0) // 只统计未删除的
        );

        // 3. 检查是否超限
        if (currentPersonCount >= application.getEntryCount()) {
            throw new RuntimeException("外协人员数量已超过申请人数限制");
        }
    }

    @Override
    public OutsourcingPerson selectByIdCard(String idCard) {

        return outsourcingPersonMapper.selectOne(
            new LambdaQueryWrapper<OutsourcingPerson>()
                .eq(OutsourcingPerson::getIdCard, idCard)
                .eq(OutsourcingPerson::getIsDeleted, 0)
        );
    }


    @Override
    public TableDataInfo<OutsourcingPerson> queryPersonList(OutsourcingPerson outsourcingPerson, PageQuery pageQuery) {
        Page<OutsourcingPerson> page = baseMapper.selectPageOutSourcingPersonList(pageQuery.build(), this.buildQueryWrapper(outsourcingPerson));
        return TableDataInfo.build(page);
    }


    /**
     * 查询条件构建
     */
    private LambdaQueryWrapper<OutsourcingPerson> buildQueryWrapper(OutsourcingPerson outsourcingPerson) {
        LambdaQueryWrapper<OutsourcingPerson> queryWrapper = new LambdaQueryWrapper<>();
        // 基础条件
        queryWrapper.like(StringUtils.isNotBlank(outsourcingPerson.getUserName()), OutsourcingPerson::getUserName, outsourcingPerson.getUserName())
                .eq(StringUtils.isNotBlank(outsourcingPerson.getIdCard()), OutsourcingPerson::getIdCard, outsourcingPerson.getIdCard())
                .eq(outsourcingPerson.getStatus() != null, OutsourcingPerson::getStatus, outsourcingPerson.getStatus())
                .eq(outsourcingPerson.getAppId() != null, OutsourcingPerson::getAppId, outsourcingPerson.getAppId())
            .apply("p.is_deleted = 0");
        // 时间范围条件：entryTime 和 endTime 都必须在 [startDate, endDate] 区间内
        if (outsourcingPerson.getEntryTime() != null && outsourcingPerson.getEndTime() != null) {
            queryWrapper.ge(OutsourcingPerson::getEntryTime,outsourcingPerson.getEntryTime())
                .le(OutsourcingPerson::getEndTime,outsourcingPerson.getEndTime());
        }
        queryWrapper.eq(outsourcingPerson.getAppId() != null,OutsourcingPerson::getAppId, outsourcingPerson.getAppId());

        return queryWrapper;
    }
    /**
     * 查询条件构建
     */
    private LambdaQueryWrapper<AccessApplication> buildQueryWrapper(AccessApplication accessApplication) {
        LambdaQueryWrapper<AccessApplication> queryWrapper = new LambdaQueryWrapper<>();

        // 基础条件：只查询未删除的记录
        queryWrapper.eq(AccessApplication::getIsDeleted, 0);

        // 添加各个查询条件
        queryWrapper
            .eq(accessApplication.getId() != null, AccessApplication::getId, accessApplication.getId())
            .like(StringUtils.isNotBlank(accessApplication.getAppUnit()), AccessApplication::getAppUnit, accessApplication.getAppUnit())
            .like(StringUtils.isNotBlank(accessApplication.getAppPerson()), AccessApplication::getAppPerson, accessApplication.getAppPerson())
            .like(StringUtils.isNotBlank(accessApplication.getOutContact()), AccessApplication::getOutContact, accessApplication.getOutContact())
            .like(StringUtils.isNotBlank(accessApplication.getOutUnit()), AccessApplication::getOutUnit, accessApplication.getOutUnit())
            .like(StringUtils.isNotBlank(accessApplication.getOutPhone()), AccessApplication::getOutPhone, accessApplication.getOutPhone())
            .eq(accessApplication.getAppDate() !=null,AccessApplication::getAppDate,accessApplication.getAppDate())
            .orderByDesc(AccessApplication::getAppDate);

        return queryWrapper;
    }

    private List<Long> findApplicationIdsByCompanyName(String companyName) {
        return Db.lambdaQuery(AccessApplication.class)
                .select(AccessApplication::getId)
                .like(AccessApplication::getOutUnit, companyName)
                .list()
                .stream()
                .map(AccessApplication::getId)
                .distinct()
                .collect(Collectors.toList());
    }

    /**
     * 分页查询
     */
    private Page<OutsourcingPerson> queryPersonPage(LambdaQueryWrapper<OutsourcingPerson> queryWrapper,
                                                    int pageNum, int pageSize) {
        // 先查询总数
        long total = outsourcingPersonMapper.selectCount(queryWrapper);

        // 无数据时快速返回
        if (total == 0) {
            return new Page<>(pageNum, pageSize, total);
        }

        // 设置分页参数
        Page<OutsourcingPerson> page = new Page<>(pageNum, pageSize, total);
        queryWrapper.last("LIMIT " + (pageNum - 1) * pageSize + "," + pageSize);

        // 执行查询
        List<OutsourcingPerson> records = outsourcingPersonMapper.selectList(queryWrapper);
        page.setRecords(records);

        return page;
    }

    /**
     * 转换为VO
     */
    private OutsourcingPersonVO convertToVO(OutsourcingPerson person) {
        OutsourcingPersonVO vo = new OutsourcingPersonVO();
        BeanUtils.copyProperties(person, vo);

        // 查询关联信息
        Optional.ofNullable(person.getAppId())
                .flatMap(appId -> Optional.ofNullable(
                        Db.lambdaQuery(AccessApplication.class)
                                .eq(AccessApplication::getId, appId)
                                .one()
                ))
                .ifPresent(app -> {
                    vo.setCompanyName(app.getOutUnit());
                    vo.setWorkArea(app.getArea());
                });

        // 计算照片数
        vo.setPhotoCount(
                (int) Stream.of(person.getIdCardFront(), person.getIdCardBack(), person.getPortraitPhoto())
                        .filter(StringUtils::isNotBlank)
                        .count()
        );

        return vo;
    }

    /**
     * 为外协人员设置IC卡编号
     * @param person 外协人员对象
     */
    @Override
    public void setIcNoForPerson(OutsourcingPerson person) {
        // 设置IC卡编号为最大值加一（从00000001开始的递增数字）
        OutsourcingPerson maxIcPerson = outsourcingPersonMapper.selectOne(
            new LambdaQueryWrapper<OutsourcingPerson>()
                .select(OutsourcingPerson::getIcNo)
                .isNotNull(OutsourcingPerson::getIcNo)
                .orderByDesc(OutsourcingPerson::getIcNo)
                .last("LIMIT 1")
        );

        if (maxIcPerson == null || maxIcPerson.getIcNo() == null) {
            // 如果没有记录，从00000001开始
            person.setIcNo("00000001");
        } else {
            try {
                // 解析现有编号，将数字部分加1
                long maxIcNo = Long.parseLong(maxIcPerson.getIcNo());
                long nextIcNo = maxIcNo + 1;
                // 格式化为8位数字，不足前面补0
                person.setIcNo(String.format("%08d", nextIcNo));
            } catch (NumberFormatException e) {
                // 出现异常时从00000001开始
//                person.setIcNo("00000001");
                throw new RuntimeException("IC卡编号生成失败", e);
            }
        }
    }


    @Override
    public void setIcNoForAppId(Long appId) {
        List<OutsourcingPerson> persons = Db.lambdaQuery(OutsourcingPerson.class)
            .eq(OutsourcingPerson::getAppId, appId)
            .list();
            for (OutsourcingPerson person : persons) {
                setIcNoForPerson(person);
                outsourcingPersonMapper.updateById(person);
            }
    }

    @Override
    public void printPersonWorkCard(List<Long> ids) {
        if (ids.isEmpty()) {
            throw new IllegalArgumentException("请选择要打印的记录");
        }

        LambdaQueryWrapper<OutsourcingPerson> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(OutsourcingPerson::getPerId, ids);
        List<OutsourcingPerson> persons = outsourcingPersonMapper.selectList(queryWrapper);

        // 创建临时工作证文件夹
        String desktopPath = System.getProperty("user.home") + File.separator + "Desktop";
        String workCardDir = desktopPath + File.separator + "临时工作证";
        File workCardFolder = new File(workCardDir);
        if (!workCardFolder.exists()) {
            workCardFolder.mkdirs();
            System.out.println("创建文件夹: " + workCardDir);
        }

        // 临时存储每张名片文档
        List<PDDocument> cardDocs = new ArrayList<>();

        for (OutsourcingPerson person : persons) {
            try {
                String companyName = accessApplicationMapper.selectOne(
                    new LambdaQueryWrapper<AccessApplication>().eq(AccessApplication::getId, person.getAppId())
                ).getOutUnit();

                // 构建需要加密的人员信息
                String personInfo = buildPersonInfoForQRCode(person);

                // 加密
                String encrypted =encryptPersonInfo(personInfo, person.getIcNo());
                System.out.println("加密结果: " + encrypted);


                // 生成带加密信息的二维码
                String qrContent = "ICNO:" + person.getIcNo() + ";DATA:" + encrypted;
//                BufferedImage qrImage = QrCodeUtil.generate(qrContent, 300, 300);

                // 修改后的代码 - 降低二维码复杂度
                QrConfig config = new QrConfig();
                config.setErrorCorrection(ErrorCorrectionLevel.L); // 使用最低纠错级别降低复杂度
                config.setMargin(1); // 减少边距
                config.setWidth(300);  // 可适当减小尺寸
                config.setHeight(300); // 可适当减小尺寸

                BufferedImage qrImage = QrCodeUtil.generate(qrContent, config);


                // 查找Logo路径
                String logoPath = null;
                String logoPath_2 = "D:\\YAXIN Projects\\OutSourcing\\yaxin-ui\\src\\assets\\logo\\yx_logo_3.png";
                String[] possibleLogoPaths = {
                    System.getProperty("user.dir") + File.separator + "yaxin-ui" + File.separator + "src" + File.separator + "assets" + File.separator + "logo" + File.separator + "yx_logo_2.png",
                    System.getProperty("user.dir") + File.separator + ".." + File.separator + "yaxin-ui" + File.separator + "src" + File.separator + "assets" + File.separator + "logo" + File.separator + "yx_logo_2.png",
                    "D:\\YAXIN Projects\\OutSourcing\\yaxin-ui\\src\\assets\\logo\\yx_logo_2.png",
                    workCardDir + File.separator + "yx_logo_2.png"
                };

                for (String path : possibleLogoPaths) {
                    if (new File(path).exists()) {
                        logoPath = path;
                        System.out.println("找到Logo文件: " + logoPath);
                        break;
                    }
                }

                // 如果找到Logo，添加到二维码中心
                if (logoPath != null) {
                    try {
                        // 加载Logo图片
                        BufferedImage logo = ImageIO.read(new File(logoPath));

                        // 计算Logo尺寸（二维码宽度的1/5）
                        int logoSize = qrImage.getWidth() / 5;

                        // 计算Logo位置（居中）
                        int x = (qrImage.getWidth() - logoSize) / 2;
                        int y = (qrImage.getHeight() - logoSize) / 2;

                        // 创建缩放后的Logo（按原图等比例缩放）
                        // 计算Logo的原始宽高比
                        double logoAspectRatio = (double) logo.getWidth() / logo.getHeight();

                        int finalLogoWidth, finalLogoHeight;

                        // 按照原图比例计算缩放后的尺寸，最大不超过二维码宽度的1/5
                        int maxLogoSize = qrImage.getWidth() / 5;

                        if (logo.getWidth() > logo.getHeight()) {
                            // 宽度大于高度，以宽度为准进行缩放
                            finalLogoWidth = Math.min(logo.getWidth(), maxLogoSize);
                            finalLogoHeight = (int) (finalLogoWidth / logoAspectRatio);
                        } else {
                            // 高度大于等于宽度，以高度为准进行缩放
                            finalLogoHeight = Math.min(logo.getHeight(), maxLogoSize);
                            finalLogoWidth = (int) (finalLogoHeight * logoAspectRatio);
                        }

                        // 按原图比例缩放Logo
                        Image scaledLogo = logo.getScaledInstance(finalLogoWidth, finalLogoHeight, Image.SCALE_SMOOTH);
                        BufferedImage resizedLogo = new BufferedImage(finalLogoWidth, finalLogoHeight, BufferedImage.TYPE_INT_ARGB);
                        Graphics2D g2d = resizedLogo.createGraphics();
                        g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
                        g2d.drawImage(scaledLogo, 0, 0, null);
                        g2d.dispose();

                        // 将Logo绘制到二维码中心
                        Graphics2D graphics = qrImage.createGraphics();
                        graphics.drawImage(resizedLogo, x, y, null);
                        graphics.dispose();
                    } catch (IOException e) {
                        System.err.println("添加二维码Logo失败: " + e.getMessage());
                    }
                } else {
                    System.out.println("警告: 未找到Logo文件，二维码将不显示Logo");
                }

                // minio下载头像
                // 获取人员照片
                BufferedImage portraitImage = null;
                if (person.getPortraitPhoto() != null && !person.getPortraitPhoto().isEmpty()) {
                    try {
                        Long portraitPhotoId = Long.parseLong(person.getPortraitPhoto());
                        person.setPortraitPhotoUrl(sysOssService.getById(portraitPhotoId).getUrl());
                        System.out.println("下载照片: " + person.getPortraitPhotoUrl());

                        portraitImage = downloadImageFromMinio(person.getPortraitPhotoUrl());
                        if (portraitImage == null) {
                            // 如果下载失败，使用默认图片
                            portraitImage = ImageIO.read(new File("C:/Users/70642/Desktop/照片.png"));
                            System.out.println("使用默认照片: " + person.getPerId());
                        }
                    } catch (Exception e) {
                        System.err.println("下载照片失败，使用默认照片（ID: " + person.getPerId() + "）: " + e.getMessage());
                        try {
                            portraitImage = ImageIO.read(new File("C:/Users/70642/Desktop/照片.png"));
                        } catch (IOException ex) {
                            throw new RuntimeException("默认照片也不存在", ex);
                        }
                    }
                } else {
                    // 如果没有照片URL，使用默认图片
                    try {
                        portraitImage = ImageIO.read(new File("C:/Users/70642/Desktop/照片.png"));
                        System.out.println("使用默认照片: " + person.getPerId());
                    } catch (IOException e) {
                        throw new RuntimeException("默认照片不存在", e);
                    }
                }


                /**
                // 生成单张名片 PDF（修改 CardPrinterUtil 让它返回 PDDocument 而不是保存文件）
                PDDocument cardDoc = CardPrinterUtil.generateCard(
                    person.getUserName(),
                    companyName,
                    person.getIcNo(),
                    "D:/YAXIN Projects/OutSourcing/yaxin-ui/src/assets/logo/yx_logo_3.png", // Logo
                    "C:/Users/70642/Desktop/照片.png", // 照片
                    qrImage
                );
                 **/
                PDDocument cardDoc = CardPrinterUtil.generateCard(
                    person.getUserName(),
                    companyName,
                    person.getIcNo(),
                    "D:/YAXIN Projects/OutSourcing/yaxin-ui/src/assets/logo/yx_logo_3.png",
                    portraitImage, // 直接传入 BufferedImage
                    qrImage
                );

                cardDocs.add(cardDoc);

            } catch (Exception e) {
                System.err.println("生成工作证失败（ID: " + person.getPerId() + "）: " + e.getMessage());
                e.printStackTrace();
            }
        }

        // 把所有名片拼成 A4 纸（8 张/页，自动分页）
        try {
            PDDocument sheet = CardSheetUtil.generateCardSheets(cardDocs);
            String outputFile = workCardDir + File.separator + "工作证批量打印.pdf";
            sheet.save(outputFile);
            sheet.close();

            for (PDDocument doc : cardDocs) {
                if(doc != null){
                    doc.close();
                }
            }

            System.out.println("✅ 批量工作证生成完成：" + outputFile);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 描述: 从Minio下载图片
     * @param imageUrl
     * @return
     */
    private BufferedImage downloadImageFromMinio(String imageUrl) {
        try {
            // 如果URL是Minio的presigned URL或者直接可访问的URL
            URL url = new URL(imageUrl);

            // 使用HttpClient下载图片
            CloseableHttpClient httpClient = HttpClients.createDefault();
            HttpGet httpGet = new HttpGet(imageUrl);

            try (CloseableHttpResponse response = httpClient.execute(httpGet)) {
                if (response.getStatusLine().getStatusCode() == 200) {
                    HttpEntity entity = response.getEntity();
                    if (entity != null) {
                        try (InputStream inputStream = entity.getContent()) {
                            return ImageIO.read(inputStream);
                        }
                    }
                }
            }

            // 如果上述方法失败，尝试直接使用URL连接
            try (InputStream in = url.openStream()) {
                return ImageIO.read(in);
            }

        } catch (Exception e) {
            System.err.println("下载图片失败: " + imageUrl + ", 错误: " + e.getMessage());
            return null;
        }
    }

    /**
     * 构建用于二维码的人员信息字符串
     * @param person 外协人员对象
     * @return 人员信息字符串
     */
    private String buildPersonInfoForQRCode(OutsourcingPerson person) {
        StringBuilder infoBuilder = new StringBuilder();
        Long portraitPhotoId = Long.parseLong(person.getPortraitPhoto());
        String portraitPhoto = sysOssService.getById(portraitPhotoId).getUrl();
        portraitPhoto = portraitPhoto.replace("http://127.0.0.1:9001/", "/");
        infoBuilder.append("name:").append(person.getUserName()).append(";");
        infoBuilder.append("phone:").append(person.getUserPhone()).append(";");
        infoBuilder.append("idCard:").append(person.getIdCard()).append(";");
        infoBuilder.append("icNo:").append(person.getIcNo()).append(";");
        infoBuilder.append("entryTime:").append(person.getEntryTime() != null ? person.getEntryTime().toString() : "").append(";");
        infoBuilder.append("endTime:").append(person.getEndTime() != null ? person.getEndTime().toString() : "").append(";");
        infoBuilder.append("photo:").append(portraitPhoto).append(";");
        return infoBuilder.toString();
    }

    /**
     * 压缩图片
     * @param imageBytes 原始图片字节数组
     * @param quality 压缩质量 (0.1-1.0)
     * @param maxWidth 最大宽度
     * @param maxHeight 最大高度
     * @return 压缩后的图片字节数组
     */
    private byte[] compressImage(byte[] imageBytes, float quality, int maxWidth, int maxHeight) {
        try {
            // 将字节数组转换为BufferedImage
            ByteArrayInputStream bais = new ByteArrayInputStream(imageBytes);
            BufferedImage originalImage = ImageIO.read(bais);

            // 计算压缩后的尺寸
            int originalWidth = originalImage.getWidth();
            int originalHeight = originalImage.getHeight();

            // 计算缩放比例
            double scale = Math.min(
                (double) maxWidth / originalWidth,
                (double) maxHeight / originalHeight
            );

            // 如果图片已经小于指定尺寸，则不放大
            scale = Math.min(scale, 1.0);

            int newWidth = (int) (originalWidth * scale);
            int newHeight = (int) (originalHeight * scale);

            // 创建缩放后的图片
            Image scaledImage = originalImage.getScaledInstance(newWidth, newHeight, Image.SCALE_SMOOTH);
            BufferedImage compressedImage = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_RGB);
            Graphics2D g2d = compressedImage.createGraphics();
            g2d.drawImage(scaledImage, 0, 0, null);
            g2d.dispose();

            // 将压缩后的图片转换为字节数组
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ImageIO.write(compressedImage, "jpg", baos);
            return baos.toByteArray();
        } catch (IOException e) {
            // 压缩失败时返回原始数据
            return imageBytes;
        }
    }


    /**
     * 加密方法（如果需要的话）
     * @param plainText 明文
     * @param icNo IC卡编号
     * @return Base64编码的加密字符串
     */
    public static String encryptPersonInfo(String plainText, String icNo) throws Exception {
        try {
            byte[] keyBytes = processKeyTo16Bytes(icNo);
            SecretKeySpec secretKey = new SecretKeySpec(keyBytes, ALGORITHM);

            Cipher cipher = Cipher.getInstance(TRANSFORMATION);
            cipher.init(Cipher.ENCRYPT_MODE, secretKey);

            byte[] encryptedBytes = cipher.doFinal(plainText.getBytes("UTF-8"));
            Base64.Encoder encoder = Base64.getEncoder();
            return encoder.encodeToString(encryptedBytes);
        } catch (Exception e) {
            throw new Exception("AES加密人员信息失败: " + e.getMessage());
        }
    }



    /**
     * 将任意长度的字符串处理为16字节的密钥
     * @param key 原始密钥字符串
     * @return 16字节的密钥数组
     */
    private  static byte[] processKeyTo16Bytes(String key) {
        if (key == null || key.isEmpty()) {
            key = "DEFAULT_KEY_1234"; // 默认密钥
        }
        byte[] keyBytes = key.getBytes();
        byte[] result = new byte[16];

        if (keyBytes.length >= 16) {
            // 如果密钥长度大于等于16，截取前16字节
            System.arraycopy(keyBytes, 0, result, 0, 16);
        } else {
            // 如果密钥长度小于16，进行填充
            System.arraycopy(keyBytes, 0, result, 0, keyBytes.length);
            // 使用密钥的循环填充剩余字节
            for (int i = keyBytes.length; i < 16; i++) {
                result[i] = keyBytes[i % keyBytes.length];
            }
        }
        return result;
    }
}
